#define WINVER 0x0500		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.

#define _WIN32_WINNT 0x0500	
#define UD_WEAVE_REQUEST 128
#define UD_UNWEAVE_REQUEST 129

#include <afx.h>
#include <afxwin.h> 
#include <tchar.h>
#include "Winsvc.h"



#include "myaspects_dac.h"
#ifndef BYTE
typedef unsigned char BYTE;
#endif

/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1997 by Joerg Koenig and the ADG mbH, Mannheim, Germany
// All rights reserved
//
// Distribute freely, except: don't remove my name from the source or
// documentation (don't take credit for my work), mark your changes (don't
// get me blamed for your possible bugs), don't alter or remove this
// notice.
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc., and
// I'll try to keep a version up to date.  I can be reached as follows:
//    J.Koenig@adg.de                 (company site)
//    Joerg.Koenig@rhein-neckar.de    (private site)
/////////////////////////////////////////////////////////////////////////////
//
// MODIFIED BY TODD C. WILSON FOR THE ROAD RUNNER NT LOGIN SERVICE.
// HOWEVER, THESE MODIFICATIONS ARE BROADER IN SCOPE AND USAGE AND CAN BE USED
// IN OTHER PROJECTS WITH NO CHANGES.
// MODIFIED LINES FLAGGED/BRACKETED BY "//!! TCW MOD"
//
/////////////////////////////////////////////////////////////////////////////


// last revised: $Date: 11.05.98 21:09 $, $Revision: 3 $


/////////////////////////////////////////////////////////////////////////////
// Acknoledgements:
//	o	Thanks to Victor Vogelpoel (VictorV@Telic.nl) for his bug-fixes
//		and enhancements.
//	o	Thanks to Todd C. Wilson (todd@mediatec.com) for the
//		"service" on Win95
//
// Changes:
//	01/21/99
//	o	Bug fixed in "DeregisterApplicationLog()"
//		thanks to Grahame Willis (grahamew@questsoftware.com.au):
//
//	04/30/98
//	o	Added two more switches to handle command line arguments:
//		-e will force a running service to stop (corresponding
//		method in this class: virtual BOOL EndService();) and
//		-s will force the service to start (method:
//		virtual BOOL StartupService())
//
//	02/05/98
//	o	Added the methods "RegisterApplicationLog()" and
//		"DeregisterApplicationLog()" (both virtual). The first one will be
//		called from "InstallService()" and creates some registry-entries
//		for a better event-log. The second one removes these entries when
//		the service will uninstall (see "RemoveService()")
//	o	The service now obtains the security identifier of the current user
//		and uses this SID for event-logging.
//	o	The memory allocated by "CommandLineToArgvW()" will now release
//		(UNICODE version only)
//	o	The service now uses a simple message catalogue for a nicer
//		event logging

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <crtdbg.h>

#include <io.h>			//!! TCW MOD
#include <fcntl.h>		//!! TCW MOD



class CNTService {
	static BOOL				m_bInstance;			// only one CNTService object per application
	
	protected:	// data members
		AspectB                 myaspect;
		MethodPC   meth1;
		ClassPC   classpc1;
		PCD  pc1;
		WeaveSpecs ws1;


		LPCTSTR					m_lpServiceName;
		LPCTSTR					m_lpDisplayName;
		DWORD					m_dwCheckPoint;
		DWORD					m_dwErr;
		BOOL					m_bDebug;			// TRUE if -d was passed to the program
		SERVICE_STATUS			m_ssStatus;			// current status of the service
		SERVICE_STATUS_HANDLE	m_sshStatusHandle;
		DWORD					m_dwControlsAccepted;	// bit-field of what control requests the
														// service will accept
														// (dflt: SERVICE_ACCEPT_STOP)
		PSID					m_pUserSID;			// the current user's security identifier
		BOOL					m_bWinNT;			// TRUE, if this is running on WinNT FALSE on Win95
		BOOL					m_fConsoleReady;

		// parameters to the "CreateService()" function:
		DWORD			m_dwDesiredAccess;		// default: SERVICE_ALL_ACCESS
		DWORD			m_dwServiceType;		// default: SERVICE_WIN32_OWN_PROCESS
		DWORD			m_dwStartType;			// default: SERVICE_AUTO_START
		DWORD			m_dwErrorControl;		// default: SERVICE_ERROR_NORMAL
		LPCTSTR			m_pszLoadOrderGroup;	// default: NULL
		DWORD			m_dwTagID;				// retrieves the tag identifier
		LPCTSTR			m_pszDependencies;		// default: NULL
		LPCTSTR			m_pszStartName;			// default: NULL
		LPCTSTR			m_pszPassword;			// default: NULL


	public:		// construction/destruction
			// If <DisplayName> is not set, then it defaults to <ServiceName>.
		CNTService(LPCTSTR ServiceName, LPCTSTR DisplayName = 0);
		~CNTService();

	private:	// forbidden functions
		CNTService( const CNTService & );
		CNTService & operator=( const CNTService & );

	public:		// overridables
			// You have to override the following two functions.
			// "Run()" will be called to start the real
			// service's activity. You must call
			//		ReportStatus(SERVICE_RUNNING);
			// before you enter your main-loop !
			// "Stop()" will be called to stop the work of
			// the service. You should break out of the mainloop
			// and return control to the CNTService class.
			//
			// In most cases these functions look like these:
			//
			//		void CMyService :: Run(DWORD argc, LPTSTR * argv) {
			//			ReportStatus(SERVICE_START_PENDING);
			//			// do some parameter processing ...
			//			ReportStatus(SERVICE_START_PENDING);
			//			// do first part of initialisation ...
			//			ReportStatus(SERVICE_START_PENDING);
			//			// do next part of initialisation
			//			// ...
			//			m_hStop = CreateEvent(0, TRUE, FALSE, 0);
			//			ReportStatus(SERVICE_RUNNING);
			//			while( WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0 ) {
			//				// do something
			//			}
			//			if( m_hStop )
			//				CloseHandle(m_hStop);
			//		}
			//
			//		void CMyService :: Stop() {
			//			if( m_hStop )
			//				SetEvent(m_hStop);
			//			ReportStatus(SERVICE_STOP_PENDING);
			//		}
		virtual void	Run(DWORD argc, LPTSTR * argv) = 0;
		virtual void	Stop() = 0;

			// Pause() and Continue() do nothing by default.
			// You can override them to handle a control request.
			// Pause() should report the status SERVICE_PAUSED
			// and Continue() should report the status SERVICE_RUNNING
			// (see ReportStatus() below).
			// Note that normally these functions will never be called. If
			// you want a service, that accepts PAUSE and CONTINUE control
			// requests, you have to to add SERVICE_ACCEPT_PAUSE_CONTINUE
			// to the m_dwControlsAccepted data member.
		virtual void	Pause();
		virtual void	Continue();

			// Shutdown() will be called, if the service manager
			// requests for the SERVICE_CONTROL_SHUTDOWN control.
			// This control type occurs, when the system shuts down.
			// If you want to process this notification, you have to
			// add SERVICE_ACCEPT_SHUTDOWN to the m_dwControlsAccepted
			// data member (and to override this function). The default
			// implementation of Shutdown() does nothing.
		virtual void	Shutdown();

			// Call "RegisterService()" after you have constructed
			// a CNTService object:
			// A typical "main()" function of a service looks like this:
			//
			//		int main( int argc, char ** argv ) {
			//			CMyService serv;
			//			exit(serv.RegisterService(argc, argv));
			//		}
			//
			// Where "CMyService" is a CNTService derived class.
			// RegisterService() checks the parameterlist. The
			// following parameters will be detected:
			//		-i			install the service (calls
			//					"InstallService()" - see below)
			//
			//			-l <account>
			//					<account> is the name of a user,
			//					under which the service shall run.
			//					This option is useful with -i only.
			//					<account> needs to have the advanced
			//					user-right "Log on as a service"
			//					(see User-Manager)
			//					<account> should have the following
			//					format: "<Domain>\<user>"
			//					"EuroS2Team\jko" for instance.
			//					The domain "." is predefined as the
			//					local machine. So one might use
			//					".\jko" too.
			//
			//			-p <password>
			//					The password of the user, under which
			//					the service shall run. Only useful
			//					with -i and -l together.
			//
			//		-u			uninstall the service (calls
			//					"RemoveService()" - see below)
			//
			//		-d			debug the service (run as console
			//					process; calls "DebugService()"
			//					see below)
			//
			//		-e			end the service (if it is running)
			//
			//		-s			start the service (if it is not running)
			//					(Note that *you* normally cannot start
			//					an NT-service from the command-line.
			//					The SCM can.)
			//
			// Do not use -l and -p, if your service is of type
			// SERVICE_KERNEL_DRIVER or SERVICE_FILE_SYSTEM_DRIVER.
			// Furthermore you canot use -i and -s together. Instead
			// you have to start the command twice, first you install
			// the service, then you start it.
			// If none of the flags -i, -u, -e, -s and -d is set, then the
			// program starts as an NT service (only the SCM can start it
			// this way!).
			// NOTE: If UNICODE is #define'd, then <argc> and <argv>
			//		will be ignored and the original commandline
			//		of the program will be used to parse the
			//		arguments !
		virtual BOOL	RegisterService(int argc, char ** argv);
		
			// "StartDispatcher()" registers one service-procedure
			// to the service control dispatcher (using the predefined
			// "ServiceMain()" function below).
			// Override this funtion, if you want to develop a
			// multithreaded NT-Service.
		virtual BOOL	StartDispatcher();

			// Override "InstallService()" to manipulate the
			// installation behavior.
			// This function will only be called, if the
			// "-i" flag was passed to "RegisterService()"
			// (see above)
			// After "InstallService()" has completed, you
			// should be able to see the service in the
			// "services" control-panel-applet.
		virtual BOOL	InstallService();

		virtual BOOL	Weave();
		virtual BOOL	Unweave();
		
			// RemoveService() removes a service from the system's
			// service-table.
			// It first tries to stop the service.
			// This function will be called only if the -u
			// flag was passed to the program. (see "RegisterService()"
			// above)
			// After removal of the service, it should no longer
			// appear in the "services" control-panel-applet.
		virtual BOOL	RemoveService();
		

			// EndService() stops a running service (if the service
			// is running as a service! Does not end a service
			// running as a console program (see DebugService()
			// below))
		virtual BOOL	EndService();

			// Start the service. Does the same as if the
			// SCM launches the program. Note that this method
			// will create a new instance of the program.
		virtual BOOL	StartupService();
		
			// Run a service as a console application. This makes it
			// easier to debug the service.
			// This function will be called only if the -d flag
			// was passed to the program(see "RegisterService()" above).
			// It transparently calls "Run()". You can simulate a
			// stop-request by pressing either Ctrl-C or Ctrl-Break (that
			// will call the "Stop()" method).
		virtual BOOL	DebugService(int argc, char **argv,BOOL faceless=FALSE);	//!! TCW MOD - added FACELESS parm to allow Win95 usage.

	protected:	// implementation
			// Override "RegisterApplicationLog()", if you want to register
			// a different message file and/or differend supported types
			// than the default.
			// The proposed message file is the application itself.
			// The proposed types are:
			// EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE
			// This method will be called from inside "InstallService()" (see above)
			// Thus if you support errors only (for instance):
			//		void CMyService :: RegisterApplicationLog(LPCTSTR filename, DWORD ) {
			//			CNTService::RegisterApplicationLog(filename, EVENTLOG_ERROR_TYPE);
			//		}
			// This method will never be called on Win95.
		virtual void	RegisterApplicationLog(
							LPCTSTR lpszProposedMessageFile,
							DWORD dwProposedTypes
						);

			// "DeregisterApplicationLog()" is called from inside "RemoveService()"
			// (see above) to clear the registry-entries made by
			// "RegisterApplicationLog()"
		virtual void	DeregisterApplicationLog();

	public:	// helpers
			// Retrieve a human-readable error message. The message
			// will be stored in <Buf> which is of size <Size>.
			// Returns a pointer to <Buf>.
		LPTSTR			GetLastErrorText(LPTSTR Buf, DWORD Size);

			// report status to the service-control-manager.
			// <CurState> can be one of:
			//		SERVICE_START_PENDING		-	the service is starting
			//		SERVICE_RUNNING				-	the service is running
			//		SERVICE_STOP_PENDING		-	the service is stopping
			//		SERVICE_STOPPED				-	the service is not running
			//		SERVICE_PAUSE_PENDING		-	the service pause is pending
			//		SERVICE_PAUSE				-	the service is paused
			//		SERVICE_CONTINUE_PENDING	-	the service is about to continue
		BOOL			ReportStatus(
							DWORD CurState,				// service's state
							DWORD WaitHint = 3000,		// expected time of operation in milliseconds
							DWORD ErrExit = 0			//!! TCW MOD - set to nonzero to flag *FATAL* error
						);

			// AddToMessageLog() writes a message to the application event-log.
			// (use EventViewer from the menu "Administrative Tools" to watch the log).
			// The <EventType> parameter can be set to one of the following values:
			//		EVENTLOG_ERROR_TYPE			Error event
			//		EVENTLOG_WARNING_TYPE		Warning event
			//		EVENTLOG_INFORMATION_TYPE	Information event
			//		EVENTLOG_AUDIT_SUCCESS		Success Audit event
			//		EVENTLOG_AUDIT_FAILURE		Failure Audit event
			// See "ReportEvent()" in the help-topics for further information.
		virtual void	AddToMessageLog(
							LPTSTR	Message,
							WORD	EventType = EVENTLOG_ERROR_TYPE,
							DWORD	dwEventID = DWORD(-1)
						);

	public:		// default handlers
			// The following functions will be used by default.
			// You can provide other handlers. If so, you have to
			// overload several of the "virtual"s above.
		static void __stdcall	ServiceCtrl(DWORD CtrlCode);
		static void __stdcall	ServiceMain(DWORD argc, LPTSTR * argv);
		static BOOL __stdcall	ControlHandler(DWORD CtrlType);

	//!! TCW MOD - added console support for Faceless Apps. Needed sometimes when something goes wrong.
	public:
		BOOL OsIsWin95() const { return ! m_bWinNT; }
		void SetupConsole();

};


// Retrieve the one and only CNTService object:
CNTService * AfxGetService();

#define STATUS_SEVERITY_WARNING          0x2
#define STATUS_SEVERITY_SUCCESS          0x0
#define STATUS_SEVERITY_INFORMATIONAL    0x1
#define STATUS_SEVERITY_ERROR            0x3


//
// MessageId: MSG_INFO_1
//
// MessageText:
//
//  %1
//
#define MSG_INFO_1                       ((DWORD)0x40000000L)

//
// MessageId: MSG_WARNING_1
//
// MessageText:
//
//  %1
//
#define MSG_WARNING_1                    ((DWORD)0x80000001L)

//
// MessageId: MSG_ERROR_1
//
// MessageText:
//
//  %1
//
#define MSG_ERROR_1                      ((DWORD)0xC0000002L)

//
// MessageId: MSG_SUCCESS_1
//
// MessageText:
//
//  %1
//
#define MSG_SUCCESS_1                    ((DWORD)0x00000003L)




#ifndef RSP_SIMPLE_SERVICE
	#define RSP_SIMPLE_SERVICE 1
#endif
#ifndef RSP_UNREGISTER_SERVICE
	#define RSP_UNREGISTER_SERVICE 0
#endif

BOOL CNTService :: m_bInstance = FALSE;

static CNTService * gpTheService = 0;			// the one and only instance

CNTService * AfxGetService() { return gpTheService; }




static LPCTSTR gszAppRegKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
static LPCTSTR gszWin95ServKey=TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices");	//!! TCW MOD


/////////////////////////////////////////////////////////////////////////////
// class CNTService -- construction/destruction

CNTService :: CNTService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName )
	: m_lpServiceName(lpServiceName)
	, m_lpDisplayName(lpDisplayName ? lpDisplayName : lpServiceName)
	, m_dwCheckPoint(0)
	, m_dwErr(0)
	, m_bDebug(FALSE)
	, m_sshStatusHandle(0)
	, m_dwControlsAccepted(SERVICE_ACCEPT_STOP)
	, m_pUserSID(0)
	, m_fConsoleReady(FALSE)
	// parameters to the "CreateService()" function:
	, m_dwDesiredAccess(SERVICE_ALL_ACCESS)
	, m_dwServiceType(SERVICE_WIN32_OWN_PROCESS)
	, m_dwStartType(SERVICE_AUTO_START)
	, m_dwErrorControl(SERVICE_ERROR_NORMAL)
	, m_pszLoadOrderGroup(0)
	, m_dwTagID(0)
	, m_pszDependencies(0)
	, m_pszStartName(0)
	, m_pszPassword(0)
{
	_ASSERTE( ! m_bInstance );



   meth1.setvalue("*"); 
   classpc1.setvalue("Telnet");
   pc1.setmethodPC(meth1);
   pc1.setclassPC(classpc1);  
   ws1.setweavetype(Before_T);
   myaspect.setweavespecs(ws1);
   myaspect.setpcd(pc1);


	OSVERSIONINFO vi;
	vi.dwOSVersionInfoSize=sizeof(vi);  // init this.
	GetVersionEx(&vi);      //lint !e534
	m_bWinNT = (vi.dwPlatformId == VER_PLATFORM_WIN32_NT);

	m_bInstance = TRUE;
	gpTheService = this;
	
	// SERVICE_STATUS members that rarely change
	m_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	m_ssStatus.dwServiceSpecificExitCode = 0;

	if( m_bWinNT ) {
		/////////////////////////////////////////////////////////////////////////
		// Providing a SID (security identifier) was contributed by Victor
		// Vogelpoel (VictorV@Telic.nl).
		// The code from Victor was slightly modified.

		// Get security information of current user
		BYTE	security_identifier_buffer[ 4096 ];
		DWORD	dwSizeSecurityIdBuffer = sizeof( security_identifier_buffer );
		PSID	user_security_identifier = NULL;

		TCHAR sUserName[ 256 ];
		DWORD dwSizeUserName  =  255;

		TCHAR sDomainName[ 256 ];
		DWORD dwSizeDomainName = 255;

		SID_NAME_USE sidTypeSecurityId;

		::ZeroMemory( sUserName, sizeof( sUserName ) );
		::ZeroMemory( sDomainName, sizeof( sDomainName ) );
		::ZeroMemory( security_identifier_buffer, dwSizeSecurityIdBuffer );

		::GetUserName( sUserName, &dwSizeUserName );

		if( ::LookupAccountName(
					0,
					sUserName,
					&security_identifier_buffer,
					&dwSizeSecurityIdBuffer,
					sDomainName,
					&dwSizeDomainName,
					&sidTypeSecurityId
				)) {
			if( ::IsValidSid( PSID(security_identifier_buffer) ) ) {
				DWORD dwSidLen = ::GetLengthSid(PSID(security_identifier_buffer));
				m_pUserSID = PSID(new BYTE [dwSidLen]);
				::CopySid(dwSidLen, m_pUserSID, security_identifier_buffer);
				_ASSERTE(::EqualSid(m_pUserSID, security_identifier_buffer));
			}
		}
	}
	/////////////////////////////////////////////////////////////////////////
}


CNTService :: ~CNTService() {
	_ASSERTE( m_bInstance );
	delete [] LPBYTE(m_pUserSID);
	m_bInstance = FALSE;
	gpTheService = 0;
}



/////////////////////////////////////////////////////////////////////////////
// class CNTService -- overridables

#define NEXT_ARG ((((*Argv)[2])==TEXT('\0'))?(--Argc,*++Argv):(*Argv)+2)


BOOL CNTService :: RegisterService( int argc, char ** argv ) {
	BOOL (CNTService::* fnc)() = &CNTService::StartDispatcher;
    DWORD Argc;
    LPTSTR * Argv;

#ifdef UNICODE
    Argv = CommandLineToArgvW(GetCommandLineW(), &Argc );
#else
    Argc = (DWORD) argc;
    Argv = argv;
#endif

    while( ++Argv, --Argc ) {
		if( Argv[0][0] == TEXT('-') ) {
			switch( Argv[0][1] ) {
				case TEXT('i'):	// install the service
					fnc = &CNTService::InstallService;
					break;
				case TEXT('l'):	// login-account (only useful with -i)
					m_pszStartName = NEXT_ARG;
					break;
				case TEXT('p'):	// password (only useful with -i)
					m_pszPassword = NEXT_ARG;
					break;
				case TEXT('u'):	// uninstall the service
					fnc = &CNTService::RemoveService;
					break;
				case TEXT('s'):	// start the service
					fnc = &CNTService::StartupService;
					break;

				case TEXT('w'):	// start the service
					fnc = &CNTService::Weave;
					break;

				case TEXT('n'):	// start the service
					fnc = &CNTService::Unweave;
					break;


				case TEXT('e'):	// end the service
					fnc = &CNTService::EndService;
					break;
				case TEXT('d'):	// debug the service
				case TEXT('f'):	//!! TCW MOD faceless non-service (Win95) mode

					m_bDebug = TRUE;
					// pass original parameters to DebugService()
					return DebugService(argc, argv,(Argv[0][1]==TEXT('f'))); //!! TCW MOD faceless non-service (Win95) mode
			}
		}
	}


	//!! TCW MOD START - if Win95, run as faceless app.
	if( fnc == &CNTService::StartDispatcher && OsIsWin95() ) {
		// act as if -f was passed anyways.
		m_bDebug = TRUE;
		return DebugService(argc, argv, TRUE);
	}
	//!! TCW MOD END - if Win95, run as faceless app.

	return (this->*fnc)();
}

BOOL CNTService :: Weave()
{
	weave(&myaspect);

	return true;
}


BOOL CNTService :: Unweave()
{
	unweave(&myaspect);

	return true;
}

BOOL CNTService :: StartDispatcher() {
    // Default implementation creates a single threaded service.
	// Override this method and provide more table entries for
	// a multithreaded service (one entry for each thread).
	SERVICE_TABLE_ENTRY dispatchTable[] =
    {
        { LPTSTR(m_lpServiceName), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
        { 0, 0 }
    };

	BOOL bRet = StartServiceCtrlDispatcher(dispatchTable);
	if( ! bRet ) {
		TCHAR szBuf[256];
        AddToMessageLog(GetLastErrorText(szBuf,255));
	}

	return bRet;
}


BOOL CNTService :: InstallService() {
    TCHAR szPath[1024];

	SetupConsole();	//!! TCW MOD - have to show the console here for the
					// diagnostic or error reason: orignal class assumed
					// that we were using _main for entry (a console app).
					// This particular usage is a Windows app (no console),
					// so we need to create it. Using SetupConsole with _main
					// is ok - does nothing, since you only get one console.

	if( GetModuleFileName( 0, szPath, 1023 ) == 0 ) {
		TCHAR szErr[256];
		_tprintf(TEXT("Unable to install %s - %s\n"), m_lpDisplayName, GetLastErrorText(szErr, 256));
		return FALSE;
	}

	BOOL bRet = FALSE;

	if( OsIsWin95() ) {	//!! TCW MOD - code added to install as Win95 service
		// Create a key for that application and insert values for
		// "EventMessageFile" and "TypesSupported"
	
	} else {
		// Real NT services go here.
		SC_HANDLE schSCManager =	OpenSCManager(
										0,						// machine (NULL == local)
										0,						// database (NULL == default)
										SC_MANAGER_ALL_ACCESS	// access required
									);
		if( schSCManager ) {
			SC_HANDLE schService =	CreateService(
										schSCManager,
										m_lpServiceName,
										m_lpDisplayName,
										m_dwDesiredAccess,
										m_dwServiceType,
										m_dwStartType,
										m_dwErrorControl,
										szPath,
										m_pszLoadOrderGroup,
										((m_dwServiceType == SERVICE_KERNEL_DRIVER ||
										  m_dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) &&
										 (m_dwStartType == SERVICE_BOOT_START ||
										  m_dwStartType == SERVICE_SYSTEM_START)) ?
											&m_dwTagID : 0,
										m_pszDependencies,
										m_pszStartName,
										m_pszPassword
									);

			if( schService ) {
				_tprintf(TEXT("%s installed.\n"), m_lpDisplayName );
				CloseServiceHandle(schService);
				bRet = TRUE;
			} else {
				TCHAR szErr[256];
				_tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
			}

			CloseServiceHandle(schSCManager);
		 } else {
			TCHAR szErr[256];
			_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
		}

		if( bRet ) {
			// installation succeeded. Now register the message file
			RegisterApplicationLog(
				szPath,		// the path to the application itself
				EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE // supported types
			);

			AddToMessageLog(TEXT("Service installed"),EVENTLOG_INFORMATION_TYPE);
		}
	}	//!! TCW MOD

	return bRet;
}


BOOL CNTService :: RemoveService() {
	BOOL bRet = FALSE;

	SetupConsole();	//!! TCW MOD - have to show the console here for the
					// diagnostic or error reason: orignal class assumed
					// that we were using _main for entry (a console app).
					// This particular usage is a Windows app (no console),
					// so we need to create it. Using SetupConsole with _main
					// is ok - does nothing, since you only get one console.


	if( OsIsWin95() ) {	//!! TCW MOD - code added to install as Win95 service
	
		
	} else {
		// Real NT services go here.
		SC_HANDLE schSCManager = OpenSCManager(
									0,						// machine (NULL == local)
									0,						// database (NULL == default)
									SC_MANAGER_ALL_ACCESS	// access required
								);
		if( schSCManager ) {
			SC_HANDLE schService =	OpenService(
										schSCManager,
										m_lpServiceName,
										SERVICE_ALL_ACCESS
									);

			if( schService ) {
				// try to stop the service
				if( ControlService(schService, SERVICE_CONTROL_STOP, &m_ssStatus) ) {
					_tprintf(TEXT("Stopping %s."), m_lpDisplayName);
					Sleep(1000);

					while( QueryServiceStatus(schService, &m_ssStatus) ) {
						if( m_ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
							_tprintf(TEXT("."));
							Sleep( 1000 );
						} else
							break;
					}

					if( m_ssStatus.dwCurrentState == SERVICE_STOPPED )
						_tprintf(TEXT("\n%s stopped.\n"), m_lpDisplayName);
						 else
							  _tprintf(TEXT("\n%s failed to stop.\n"), m_lpDisplayName);
				}

				// now remove the service
				if( DeleteService(schService) ) {
					_tprintf(TEXT("%s removed.\n"), m_lpDisplayName);
					bRet = TRUE;
				} else {
					TCHAR szErr[256];
					_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
				}

				CloseServiceHandle(schService);
			} else {
				TCHAR szErr[256];
				_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
			}

			  CloseServiceHandle(schSCManager);
		 } else {
			TCHAR szErr[256];
			_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
		}

		if( bRet )
			DeregisterApplicationLog();
	}

	return bRet;
}


BOOL CNTService :: EndService() {
	BOOL bRet = FALSE;

	SC_HANDLE schSCManager = ::OpenSCManager(
								0,						// machine (NULL == local)
								0,						// database (NULL == default)
								SC_MANAGER_ALL_ACCESS	// access required
							);
	if( schSCManager ) {
		SC_HANDLE schService =	::OpenService(
									schSCManager,
									m_lpServiceName,
									SERVICE_ALL_ACCESS
								);

		if( schService ) {
			// try to stop the service
			if( ::ControlService(schService, SERVICE_CONTROL_STOP, &m_ssStatus) ) {
				_tprintf(TEXT("Stopping %s."), m_lpDisplayName);
				::Sleep(1000);

				while( ::QueryServiceStatus(schService, &m_ssStatus) ) {
					if( m_ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
						_tprintf(TEXT("."));
						::Sleep( 1000 );
					} else
						break;
				}

				if( m_ssStatus.dwCurrentState == SERVICE_STOPPED )
					bRet = TRUE, _tprintf(TEXT("\n%s stopped.\n"), m_lpDisplayName);
                else
                    _tprintf(TEXT("\n%s failed to stop.\n"), m_lpDisplayName);
			}

			::CloseServiceHandle(schService);
		} else {
			TCHAR szErr[256];
			_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
		}

        ::CloseServiceHandle(schSCManager);
    } else {
		TCHAR szErr[256];
		_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
	}

	return bRet;
}


BOOL CNTService :: StartupService() {
	BOOL bRet = FALSE;

	SC_HANDLE schSCManager = ::OpenSCManager(
								0,						// machine (NULL == local)
								0,						// database (NULL == default)
								SC_MANAGER_ALL_ACCESS	// access required
							);
	if( schSCManager ) {
		SC_HANDLE schService =	::OpenService(
									schSCManager,
									m_lpServiceName,
									SERVICE_ALL_ACCESS
								);

		if( schService ) {
			// try to start the service
			_tprintf(TEXT("Starting up %s."), m_lpDisplayName);
			if( ::StartService(schService, 0, 0) ) {
				Sleep(1000);

				while( ::QueryServiceStatus(schService, &m_ssStatus) ) {
					if( m_ssStatus.dwCurrentState == SERVICE_START_PENDING ) {
						_tprintf(TEXT("."));
						Sleep( 1000 );
					} else
						break;
				}

				if( m_ssStatus.dwCurrentState == SERVICE_RUNNING )
					bRet = TRUE, _tprintf(TEXT("\n%s started.\n"), m_lpDisplayName);
                else
                    _tprintf(TEXT("\n%s failed to start.\n"), m_lpDisplayName);
			} else {
				// StartService failed
				TCHAR szErr[256];
				_tprintf(TEXT("\n%s failed to start: %s\n"), m_lpDisplayName, GetLastErrorText(szErr,256));
			}

			::CloseServiceHandle(schService);
		} else {
			TCHAR szErr[256];
			_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
		}

        ::CloseServiceHandle(schSCManager);
    } else {
		TCHAR szErr[256];
		_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
	}

	return bRet;
}



////////////////////////////////////////////////////////////////////////////


BOOL CNTService :: DebugService(int argc, char ** argv, BOOL faceless) {
    DWORD dwArgc;
    LPTSTR *lpszArgv;

    dwArgc   = (DWORD) argc;
    lpszArgv = argv;

	if( !faceless ) {	//!! TCW MOD - no faceless, so give it a face.
		SetupConsole();	//!! TCW MOD - make the console for debugging
	   _tprintf(TEXT("Debugging %s.\n"), m_lpDisplayName);

		SetConsoleCtrlHandler(ControlHandler, TRUE);
	}

	//!! TCW MOD START - if Win95, register server
	typedef DWORD (__stdcall *fp_RegServProc)(DWORD dwProcessId,DWORD dwType);
	fp_RegServProc fncptr=NULL;


	//!! TCW MOD END - if Win95, register server


    Run(dwArgc, lpszArgv);


	if (fncptr!=NULL)		//!! TCW MOD - if it's there, remove it: our run is over
		(*fncptr)(0, RSP_UNREGISTER_SERVICE);

	return TRUE;
}


void CNTService :: Pause() {
}


void CNTService :: Continue() {
}


void CNTService :: Shutdown() {
}


/////////////////////////////////////////////////////////////////////////////
// class CNTService -- default handlers

void __stdcall CNTService :: ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
	_ASSERTE( gpTheService != 0 );
OutputDebugString("a\n");
	// register our service control handler:
	gpTheService->m_sshStatusHandle =	RegisterServiceCtrlHandler(
											gpTheService->m_lpServiceName,
											CNTService::ServiceCtrl
										);
OutputDebugString("b\n");
	if( gpTheService->m_sshStatusHandle )
OutputDebugString("b1\n");
		// report the status to the service control manager.
		if( gpTheService->ReportStatus(SERVICE_START_PENDING) ){
OutputDebugString("b11\n");
			gpTheService->Run( dwArgc, lpszArgv );
OutputDebugString("b12\n");
    }
OutputDebugString("b2\n");
	// try to report the stopped status to the service control manager.
  if( gpTheService->m_sshStatusHandle ) {
OutputDebugString("b3\n");
		gpTheService->ReportStatus(SERVICE_STOPPED);
  }
OutputDebugString("c\n");
}


void __stdcall CNTService :: ServiceCtrl(DWORD dwCtrlCode) {
	_ASSERTE( gpTheService != 0 );

	// Handle the requested control code.
	switch( dwCtrlCode ) {
		case SERVICE_CONTROL_STOP:
			// Stop the service.
			gpTheService->m_ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
			gpTheService->Stop();
			break;

		case SERVICE_CONTROL_PAUSE:
			gpTheService->m_ssStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
			gpTheService->Pause();
			break;

		case SERVICE_CONTROL_CONTINUE:
			gpTheService->m_ssStatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
			gpTheService->Continue();
			break;

		case SERVICE_CONTROL_SHUTDOWN:
			gpTheService->Shutdown();
			break;

		case SERVICE_CONTROL_INTERROGATE:
			// Update the service status.
			gpTheService->ReportStatus(gpTheService->m_ssStatus.dwCurrentState);
			break;


	    case UD_WEAVE_REQUEST:
			gpTheService->Weave();
		  break;

	  case UD_UNWEAVE_REQUEST:
		  gpTheService->Unweave();

			 break;

		default:
			// invalid control code
			break;
	}

}


BOOL __stdcall CNTService :: ControlHandler(DWORD dwCtrlType) {
	_ASSERTE(gpTheService != 0);
	switch( dwCtrlType ) {
		case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
		case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
			_tprintf(TEXT("Stopping %s.\n"), gpTheService->m_lpDisplayName);
			gpTheService->Stop();
			return TRUE;
	}
	return FALSE;
}


/////////////////////////////////////////////////////////////////////////////
// class CNTService -- helpers

//!! TCW MOD - added DWORD dwErrExit for error exit value. Defaults to zero
BOOL CNTService :: ReportStatus(
						DWORD dwCurrentState,
						DWORD dwWaitHint,
						DWORD dwErrExit ) {
	BOOL fResult = TRUE;

	if( !m_bDebug ) { // when debugging we don't report to the SCM
        if( dwCurrentState == SERVICE_START_PENDING)
            m_ssStatus.dwControlsAccepted = 0;
        else
            m_ssStatus.dwControlsAccepted = m_dwControlsAccepted;

        m_ssStatus.dwCurrentState = dwCurrentState;
        m_ssStatus.dwWin32ExitCode = NO_ERROR;
        m_ssStatus.dwWaitHint = dwWaitHint;

			//!! TCW MOD START - added code to support error exiting
			m_ssStatus.dwServiceSpecificExitCode = dwErrExit;
			if (dwErrExit!=0)
				m_ssStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
			//!! TCW MOD END - added code to support error exiting

        if( dwCurrentState == SERVICE_RUNNING ||
            dwCurrentState == SERVICE_STOPPED )
            m_ssStatus.dwCheckPoint = 0;
        else
            m_ssStatus.dwCheckPoint = ++m_dwCheckPoint;

        // Report the status of the service to the service control manager.
        if (!(fResult = SetServiceStatus( m_sshStatusHandle, &m_ssStatus))) {
            AddToMessageLog(TEXT("SetServiceStatus() failed"));
        }
    }

    return fResult;
}


void CNTService :: AddToMessageLog(LPTSTR lpszMsg, WORD wEventType, DWORD dwEventID) {
	m_dwErr = GetLastError();

	// use default message-IDs
	if( dwEventID == DWORD(-1) ) {
		switch( wEventType ) {
			case EVENTLOG_ERROR_TYPE:
				dwEventID = MSG_ERROR_1;
				break;
			case EVENTLOG_WARNING_TYPE:
				dwEventID = MSG_WARNING_1;
				break;
			case EVENTLOG_INFORMATION_TYPE:
				dwEventID = MSG_INFO_1;
				break;
			case EVENTLOG_AUDIT_SUCCESS:
				dwEventID = MSG_INFO_1;
				break;
			case EVENTLOG_AUDIT_FAILURE:
				dwEventID = MSG_INFO_1;
				break;
			default:
				dwEventID = MSG_INFO_1;
				break;
		}
	}

	// Use event logging to log the error.
	HANDLE hEventSource = RegisterEventSource(0, m_lpServiceName);

	if( hEventSource != 0 ) {
		LPCTSTR lpszMessage = lpszMsg;

		ReportEvent(
			hEventSource,	// handle of event source
			wEventType,		// event type
			0,				// event category
			dwEventID,		// event ID
			m_pUserSID,		// current user's SID
			1,				// strings in lpszStrings
			0,				// no bytes of raw data
			&lpszMessage,	// array of error strings
			0				// no raw data
		);

		::DeregisterEventSource(hEventSource);
    }
}


LPTSTR CNTService :: GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ) {
    LPTSTR lpszTemp = 0;

    DWORD dwRet =	::FormatMessage(
						FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
						0,
						GetLastError(),
						LANG_NEUTRAL,
						(LPTSTR)&lpszTemp,
						0,
						0
					);

    if( !dwRet || (dwSize < dwRet+14) )
        lpszBuf[0] = TEXT('\0');
    else {
        lpszTemp[_tcsclen(lpszTemp)-2] = TEXT('\0');  //remove cr/nl characters
        _tcscpy(lpszBuf, lpszTemp);
    }

    if( lpszTemp )
        LocalFree(HLOCAL(lpszTemp));

    return lpszBuf;
}

/////////////////////////////////////////////////////////////////////////////
// class CNTService -- implementation

void CNTService :: RegisterApplicationLog( LPCTSTR lpszFileName, DWORD dwTypes ) {
	TCHAR szKey[256];
	_tcscpy(szKey, gszAppRegKey);
	_tcscat(szKey, m_lpServiceName);
	HKEY hKey = 0;
	LONG lRet = ERROR_SUCCESS;
	
}


void CNTService :: DeregisterApplicationLog() {
	TCHAR szKey[256];
	_tcscpy(szKey, gszAppRegKey);
	_tcscat(szKey, m_lpServiceName);
	HKEY hKey = 0;
	LONG lRet = ERROR_SUCCESS;

	
}

////////////////////////////////////////////////////////

//!! TCW MOD - function to create console for faceless apps if not already there
void CNTService::SetupConsole() {
	if( !m_fConsoleReady ) {
		AllocConsole();	// you only get 1 console.

		// lovely hack to get the standard io (printf, getc, etc) to the new console. Pretty much does what the
		// C lib does for us, but when we want it, and inside of a Window'd app.
		// The ugly look of this is due to the error checking (bad return values. Remove the if xxx checks if you like it that way.
		DWORD astds[3]={STD_OUTPUT_HANDLE,STD_ERROR_HANDLE,STD_INPUT_HANDLE};
		FILE *atrgs[3]={stdout,stderr,stdin};
		for( register int i=0; i<3; i++ ) {
			long hand=(long)GetStdHandle(astds[i]);
			if( hand!=(long)INVALID_HANDLE_VALUE ) {
				int osf=_open_osfhandle(hand,_O_TEXT);
				if( osf!=-1 ) {
					FILE *fp=_fdopen(osf,(astds[i]==STD_INPUT_HANDLE) ? "r" : "w");
					if( fp!=NULL ) {
						*(atrgs[i])=*fp;
						setvbuf(fp,NULL,_IONBF,0);
					}
				}
			}
		}
		m_fConsoleReady=TRUE;
	}
}




#define WIN32_LEAN_AND_MEAN

#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include <winsock2.h>
#include <stdio.h>

#define ERR_BUFF_LEN 1024

#pragma comment( lib, "wsock32" )
#pragma comment( lib, "advapi32" ) 

extern long restartCount;

extern volatile BOOL requestReset;

//"Share handles" security descriptor
SECURITY_ATTRIBUTES security = {
	sizeof(SECURITY_ATTRIBUTES),
		NULL,
		TRUE
};

DWORD __stdcall run_sock(void*);
DWORD __stdcall run_console(void*);
DWORD __stdcall run_error(void*);

class Telnet

{
public:

	Telnet(){};
	~Telnet() {};


//Winsock Data block
WSADATA wi;
//Thread handles
DWORD thrid_sock;
DWORD thrid_console;
DWORD thrid_error;
//Stdin/out handles
HANDLE stdinput;
HANDLE stdoutput;
HANDLE stderror;
// "Input" pipe for the console.
HANDLE readInput;
HANDLE writeInput;
// Console "Output" pipe.
HANDLE readOutput;
HANDLE writeOutput;
// Console stderr pipe.
HANDLE readError;
HANDLE writeError;
//Main "listen" socket.
sockaddr_in myaddr;
SOCKET sock;
//Telnet connection socket
SOCKET talk;

	char username[64];
	char password[64];
	char domain[64];

//Console Process creation information
STARTUPINFO si;

PROCESS_INFORMATION pi;

HANDLE m_SocketClosed;



#define BUFF_SIZE 256
static BOOL
_org_getAndAllocateLogonSid
(
	HANDLE hToken,
	PSID *pLogonSid
)
{
	PTOKEN_GROUPS	ptgGroups = NULL;
	DWORD			cbBuffer  = 0;  	/* allocation size */
	DWORD			dwSidLength;		/* required size to hold Sid */
	UINT			i;					/* Sid index counter */
	BOOL			bSuccess  = FALSE;	/* assume this function will fail */

	*pLogonSid = NULL; // invalidate pointer

	/*
	** Get neccessary memory allocation
	*/
	GetTokenInformation(hToken, TokenGroups, ptgGroups, cbBuffer, &cbBuffer);

	if (cbBuffer)
		ptgGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuffer);

	/*
	**	Get Sids for all groups the user belongs to
	*/
	bSuccess = GetTokenInformation(
					hToken,
					TokenGroups,
					ptgGroups,
					cbBuffer,
					&cbBuffer
				);
	if (bSuccess == FALSE)
		goto finish3;

	/*
	** Get the logon Sid by looping through the Sids in the token
	*/
	for(i = 0 ; i < ptgGroups->GroupCount ; i++)
	{
		if (ptgGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID)
		{
			/*
			** insure we are dealing with a valid Sid
			*/
			bSuccess = IsValidSid(ptgGroups->Groups[i].Sid);
			if (bSuccess == FALSE)
				goto finish3;

			/*
			** get required allocation size to copy the Sid
			*/
			dwSidLength=GetLengthSid(ptgGroups->Groups[i].Sid);

			/*
			** allocate storage for the Logon Sid
			*/
			if(
				(*pLogonSid = (PSID)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidLength))
				==
				NULL
			)
			{
				bSuccess = FALSE;
				goto finish3;
			}

			/*
			** copy the Logon Sid to the storage we just allocated
			*/
			bSuccess = CopySid(
							dwSidLength,
							*pLogonSid,
							ptgGroups->Groups[i].Sid
						);

			break;
		}
	}


finish3:
	/*
	** free allocated resources
	*/
	if (bSuccess == FALSE)
	{
		if(*pLogonSid != NULL)
		{
			HeapFree(GetProcessHeap(), 0, *pLogonSid);
			*pLogonSid = NULL;
		}
	}

	if (ptgGroups != NULL)
		HeapFree(GetProcessHeap(), 0, ptgGroups);

	return bSuccess;
}
 
 
static BOOL
_org_setSidOnAcl
(
	PSID pSid,
	PACL pAclSource,
	PACL *pAclDestination,
	DWORD AccessMask,
	BOOL bAddSid,
	BOOL bFreeOldAcl
)
{
	ACL_SIZE_INFORMATION	AclInfo;
	DWORD					dwNewAclSize;
	LPVOID					pAce;
	DWORD					AceCounter;
	BOOL					bSuccess=FALSE;

	/*
	** If we were given a NULL Acl, just provide a NULL Acl
	*/
	if (pAclSource == NULL)
	{
		*pAclDestination = NULL;
		return TRUE;
	}

	if (!IsValidSid(pSid)) return FALSE;

	/*
	**	Get ACL's parameters
	*/
	if (
		!GetAclInformation(
			pAclSource,
			&AclInfo,
			sizeof(ACL_SIZE_INFORMATION),
			AclSizeInformation
		)
	)
		return FALSE;

	/*
	**	Compute size for new ACL, based on
	**	addition or subtraction of ACE
	*/
	if (bAddSid)
	{
		dwNewAclSize = AclInfo.AclBytesInUse  +
							sizeof(ACCESS_ALLOWED_ACE)  +
							GetLengthSid(pSid)          -
							sizeof(DWORD)               ;
	}
	else
	{
		dwNewAclSize = AclInfo.AclBytesInUse  -
							sizeof(ACCESS_ALLOWED_ACE)  -
							GetLengthSid(pSid)          +
							sizeof(DWORD)               ;
	}

	*pAclDestination = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize);
	if(*pAclDestination == NULL)
		return FALSE;

	/*
	** initialize new Acl
	*/
	bSuccess = InitializeAcl(*pAclDestination, dwNewAclSize, ACL_REVISION);
	if (bSuccess == FALSE)
		goto finish5;

	/*
	** copy existing ACEs to new ACL
	*/
	for(AceCounter = 0 ; AceCounter < AclInfo.AceCount ; AceCounter++)
	{
		/*
		** fetch existing ace
		*/
		bSuccess = GetAce(pAclSource, AceCounter, &pAce);
		if (bSuccess == FALSE)
			goto finish5;

		/*
		** check to see if we are removing the ACE
		*/
		if (!bAddSid)
		{
			/*
			** we only care about ACCESS_ALLOWED ACEs
			*/
			if ((((PACE_HEADER)pAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE)
			{
				PSID pTempSid=(PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
				/*
				** if the Sid matches, skip adding this Sid
				*/
				if (EqualSid(pSid, pTempSid)) continue;
			}
		}

		/*
		** append ACE to ACL
		*/
		bSuccess = AddAce(
						*pAclDestination,
						ACL_REVISION,
						0,  // maintain Ace order
						pAce,
						((PACE_HEADER)pAce)->AceSize
					);
		if (bSuccess == FALSE)
			goto finish5;

	}

	/*
	** If appropriate, add ACE representing pSid
	*/
	if (bAddSid)
		bSuccess = AddAccessAllowedAce(
						*pAclDestination,
						ACL_REVISION,
						AccessMask,
						pSid
					);

finish5:
	/*
	** free memory if an error occurred
	*/
	if (!bSuccess)
	{
		if(*pAclDestination != NULL)
			HeapFree(GetProcessHeap(), 0, *pAclDestination);
	}
	else if (bFreeOldAcl)
		HeapFree(GetProcessHeap(), 0, pAclSource);

	return bSuccess;
}

static BOOL
_org_setWinstaDesktopSecurity
(
	HWINSTA hWinsta,
	HDESK hDesktop,
	PSID pLogonSid,
	BOOL bGrant,
	HANDLE hToken
)
{
	SECURITY_INFORMATION	si = DACL_SECURITY_INFORMATION;
	PSECURITY_DESCRIPTOR	sdDesktop = NULL;
	PSECURITY_DESCRIPTOR	sdWinsta = NULL;
	SECURITY_DESCRIPTOR		sdNewDesktop;
	SECURITY_DESCRIPTOR		sdNewWinsta;
	DWORD					sdDesktopLength	= 0;	/* allocation size */
	DWORD					sdWinstaLength	= 0;	/* allocation size */
	PACL					pDesktopDacl;		/* previous Dacl on Desktop */
	PACL					pWinstaDacl;        /* previous Dacl on Winsta */
	PACL					pNewDesktopDacl	= NULL;	/* new Dacl for Desktop */
	PACL					pNewWinstaDacl	= NULL;	/* new Dacl for Winsta */
	BOOL					bDesktopDaclPresent;
	BOOL					bWinstaDaclPresent;
	BOOL					bDaclDefaultDesktop;
	BOOL					bDaclDefaultWinsta;
	BOOL					bSuccess		= FALSE;
	PSID					pUserSid = NULL;

	/*
	** Obtain security descriptor for Desktop
	*/
	GetUserObjectSecurity(
		hDesktop,
		&si,
		sdDesktop,
		sdDesktopLength,
		&sdDesktopLength
	);

	if (sdDesktopLength)
		sdDesktop = (PSECURITY_DESCRIPTOR)HeapAlloc(
						GetProcessHeap(), HEAP_ZERO_MEMORY, sdDesktopLength);

	bSuccess = GetUserObjectSecurity(
		hDesktop,
		&si,
		sdDesktop,
		sdDesktopLength,
		&sdDesktopLength
	);

	if (bSuccess == FALSE)
		goto finish4;

	/*
	** Obtain security descriptor for Window station
	*/
	GetUserObjectSecurity(
		hWinsta,
		&si,
		sdWinsta,
		sdWinstaLength,
		&sdWinstaLength
	);

	if (sdWinstaLength)
		sdWinsta = (PSECURITY_DESCRIPTOR)HeapAlloc(
							GetProcessHeap(), HEAP_ZERO_MEMORY, sdWinstaLength);

	bSuccess = GetUserObjectSecurity(
		hWinsta,
		&si,
		sdWinsta,
		sdWinstaLength,
		&sdWinstaLength
	);

	if (bSuccess == FALSE)
		goto finish4;

	/*
	** Obtain DACL from security descriptor for desktop
	*/
	bSuccess = GetSecurityDescriptorDacl(
					sdDesktop,
					&bDesktopDaclPresent,
					&pDesktopDacl,
					&bDaclDefaultDesktop
				);

	if (bSuccess == FALSE)
		goto finish4;

	/*
	** Obtain DACL from security descriptor for Window station
	*/
	bSuccess = GetSecurityDescriptorDacl(
					sdWinsta,
					&bWinstaDaclPresent,
					&pWinstaDacl,
					&bDaclDefaultWinsta
				);

	if (bSuccess == FALSE)
		goto finish4;

	/*
	** Create new DACL with Logon and User Sid for Desktop
	*/
	if(bDesktopDaclPresent) {
		bSuccess = setSidOnAcl(
			pLogonSid,
			pDesktopDacl,
			&pNewDesktopDacl,
			GENERIC_READ | GENERIC_WRITE | READ_CONTROL
			| DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW
			| DESKTOP_CREATEMENU | DESKTOP_SWITCHDESKTOP
			| DESKTOP_ENUMERATE,
			bGrant,
			FALSE
		);

		if (bSuccess == FALSE)
			goto finish4;
	}

	/*
	** Create new DACL with Logon and User Sid for Window station
	*/
	if(bWinstaDaclPresent)
	{
		bSuccess = setSidOnAcl(
						pLogonSid,
						pWinstaDacl,
						&pNewWinstaDacl,
						GENERIC_READ | GENERIC_WRITE | READ_CONTROL
						| WINSTA_ACCESSGLOBALATOMS
						| WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES
						| WINSTA_ACCESSCLIPBOARD | WINSTA_ENUMERATE
						| WINSTA_EXITWINDOWS,
						bGrant,
						FALSE
					);

		if (bSuccess == FALSE)
			goto finish4;
	}
 
	/*
	** Initialize the target security descriptor for Desktop
	*/
	if (bDesktopDaclPresent)
	{
		bSuccess = InitializeSecurityDescriptor(
						&sdNewDesktop,
						SECURITY_DESCRIPTOR_REVISION
					);

		if (bSuccess == FALSE)
			goto finish4;
	}

	/*
	** Initialize the target security descriptor for Window station
	*/
	if(bWinstaDaclPresent)
	{
		bSuccess = InitializeSecurityDescriptor(
						&sdNewWinsta,
						SECURITY_DESCRIPTOR_REVISION
					);

		if (bSuccess == FALSE)
			goto finish4;
	}

	/*
	** Apply new ACL to the Desktop security descriptor
	*/
	if(bDesktopDaclPresent)
	{
		bSuccess = SetSecurityDescriptorDacl(
						&sdNewDesktop,
						TRUE,
						pNewDesktopDacl,
						bDaclDefaultDesktop
					);

		if (bSuccess == FALSE)
			goto finish4;
	}

	/*
	** Apply new ACL to the Window station security descriptor
	*/
	if(bWinstaDaclPresent)
	{
		bSuccess = SetSecurityDescriptorDacl(
						&sdNewWinsta,
						TRUE,
						pNewWinstaDacl,
						bDaclDefaultWinsta
					);

		if (bSuccess == FALSE)
			goto finish4;
	}

	/*
	** Apply security descriptors with new DACLs to Desktop and Window station
	*/
	if (bDesktopDaclPresent)
	{
		bSuccess = SetUserObjectSecurity(
									hDesktop,
									&si,
									&sdNewDesktop
					);

		if (bSuccess == FALSE)
			goto finish4;
	}

	if(bWinstaDaclPresent)
		bSuccess = SetUserObjectSecurity(
									hWinsta,
									&si,
									&sdNewWinsta
					);

	if (bSuccess == FALSE)
		goto finish4;
finish4:
	if (sdDesktop != NULL)
		HeapFree(GetProcessHeap(), 0, sdDesktop);

	if (sdWinsta != NULL)
		HeapFree(GetProcessHeap(), 0, sdWinsta);

	if (pNewDesktopDacl != NULL)
		HeapFree(GetProcessHeap(), 0, pNewDesktopDacl);

	if (pNewWinstaDacl != NULL)
		HeapFree(GetProcessHeap(), 0, pNewWinstaDacl);

	return bSuccess;
}

static BOOL
_org_allowDesktopAccess
(HANDLE hToken)
{
	HWINSTA	hWinsta = NULL;
	HDESK	hDesktop = NULL;
	PSID	pLogonSid = NULL;
	BOOL	ok = FALSE;

	if (!getAndAllocateLogonSid(hToken, &pLogonSid))
		return FALSE;

	hWinsta=GetProcessWindowStation();
	hDesktop=GetThreadDesktop(GetCurrentThreadId());
	 
	ok = SetHandleInformation(hDesktop,
							  HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
	if (!ok)
		return FALSE;

	ok = SetHandleInformation(hWinsta,
							  HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
	if (!ok)
		return FALSE;

	ok = setWinstaDesktopSecurity(hWinsta, hDesktop, pLogonSid, TRUE, hToken);

	if(pLogonSid != NULL)
		HeapFree(GetProcessHeap(), 0, pLogonSid);

	return ok;
}


char 
_org_GetCharFromClient
()
{
	char ch;
	int read=recv(talk,&ch,1,0);
	if(!read)
	{
		ch = -1;
		printf("Socket broken at other end....\n");
	}
	return ch;
}


BOOL 
_org_GetString
(char * prompt,char * value,BOOL maskinput)
{
	char crlf[3] = {0x0D, 0x0A, 0x00};
	send(talk,crlf,strlen(crlf),0);
	send(talk,prompt,strlen(prompt),0);
	char c = GetCharFromClient();
	int index = 0;
	while(c >0)
	{
		if(c == 0x0A) return TRUE;
		if(!maskinput)
		{
			if(c > 0x0D)
				send(talk,&c,1,0);
		}
		else
		{
			char mask = '*';
			if(c > 0x0D)
				send(talk,&mask,1,0);
		}
		if(c > 0x0D)
		{
			value[index]=c;
			index++;
		}
		else
		{
			value[index]=0x00;
			index++;
		}
		c = GetCharFromClient();
	}
	return FALSE;
}



void 
_org_StartNetwork
()
{
	// Startup Winsock
	WSAStartup(0x0101,&wi);
	
	//create the stop event
	m_SocketClosed = CreateEvent(0, TRUE, FALSE, 0);

	// Create a Socket to connect to the remote doodaad...
	sock = socket(AF_INET,SOCK_STREAM,0);
	
	// Get our own name so we can get our IP...
	char hostname[64];
	gethostname(hostname,64);
	
	// Get our hostent info
	hostent* hent = gethostbyname("127.0.0.1");
	
	// Bind our address and the telnet port to the socket
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(7013);
	myaddr.sin_addr.s_addr = *(DWORD*)hent->h_addr_list[0];

}

bool 
_org_Bind
()
{

	if( bind(sock,(sockaddr*)&myaddr,sizeof(sockaddr)))
	{
		return true;
	}

}

void 
_org_Listen
()
{
	listen(sock,1);

}

void 
_org_Accept_Connection
()

{
	talk = accept(sock,NULL,NULL);
}



void 
_org_Print_Welcome_String
()
{
	char * msg = "Telnet Server Started";
	send(talk,msg,strlen(msg),0);
	char crlf[3] = {0x0D, 0x0A, 0x00};
	send(talk,crlf,strlen(crlf),0);
	send(talk,crlf,strlen(crlf),0);
	send(talk,crlf,strlen(crlf),0);


}

void 
_org_Create_Handles_and_Pipes
()
{

	// Save the "Standard" handles.
	stdinput = GetStdHandle(STD_INPUT_HANDLE);
	stdoutput = GetStdHandle(STD_OUTPUT_HANDLE);
	stderror = GetStdHandle(STD_ERROR_HANDLE);
	
	// Create the "Input" pipe for the console to get stuff from us
	CreatePipe(&readInput,&writeInput,&security,0);
	// Set the Default "Input" handle of the console to be this pipe
	SetStdHandle(STD_INPUT_HANDLE,readInput);
	
	// Create the console's "Output" pipe by which we get stuff back
	CreatePipe(&readOutput,&writeOutput,&security,0);
	// Set the "Output" handle to be this pipe.
	SetStdHandle(STD_OUTPUT_HANDLE,writeOutput);
	
	// Create the console's Error pipe
	CreatePipe(&readError,&writeError,&security,0);
	// Set the stderr handle to be our pipe.
	SetStdHandle(STD_ERROR_HANDLE,writeError);

}

bool 
_org_Get_Authenticate_Info
()
{
	if(GetString("Username:",username,FALSE))
 	 if(GetString("Password:",password,TRUE))
	   if(GetString("  Domain:",domain,FALSE))
		   return true;

	return false;

}

void 
_org_Close_Sockets_and_Handles
()
{
	closesocket(talk);
	closesocket(sock);
	CloseHandle(m_SocketClosed);
	CloseHandle(readInput);
	CloseHandle(writeInput);
	CloseHandle(readOutput);
	CloseHandle(writeOutput);
	CloseHandle(readError);
	CloseHandle(writeError);
	SetStdHandle(STD_INPUT_HANDLE,stdinput);
	SetStdHandle(STD_OUTPUT_HANDLE,stdoutput);
	SetStdHandle(STD_ERROR_HANDLE,stderror);

}

void 
_org_Close_Network
()
{
WSACleanup();
}
void 
_org_Cycle
()
{

char crlf[3] = {0x0D, 0x0A, 0x00};

	StartNetwork();

    if (Bind())
		return;

	
	// Listen for an incomming connections...
	

	Listen();
	// accept an incoming

   Accept_Connection();

	//print the welcome string

   Print_Welcome_String();

   
   //get the username and password




	Create_Handles_and_Pipes();



	if (Get_Authenticate_Info())

	{
		send(talk,crlf,strlen(crlf),0);
		send(talk,crlf,strlen(crlf),0);

		// Create a thread to handle socket input
//		unsigned int th1 = _beginthreadex(NULL,0,&Telnet::run_sock,NULL,0,&thrid_sock);
		HANDLE th1,th2 ,th3;
		th1=CreateThread(NULL , 0 , run_sock, this, 0 , &thrid_sock);
		
		// Create our thread to console input
		th2=CreateThread(NULL,0,run_console,this,0,&thrid_console);
		
		// Create a thread to handle error input
		th3=CreateThread(NULL,0,run_error,this,0,&thrid_error);
		


		HANDLE          hUserToken;


		if(LogonUser(
			username,
			domain,
			password,
			LOGON32_LOGON_INTERACTIVE,
			LOGON32_PROVIDER_DEFAULT,
			&hUserToken ))
		{

			if(allowDesktopAccess(hUserToken))
			{

				ZeroMemory(&si,sizeof(STARTUPINFO));
				si.cb = sizeof(STARTUPINFO);
				si.lpReserved = NULL;
				si.lpReserved2 = NULL;
				si.cbReserved2 = 0;
				si.lpDesktop = NULL;
				si.wShowWindow = SW_HIDE;
				char SysDir[256];
				GetSystemDirectory(SysDir,256);
				si.dwFlags = 0;
				si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
				si.hStdInput = readInput;
				si.hStdOutput = writeOutput;
				si.hStdError = writeError;
				si.wShowWindow = SW_HIDE;

				
				// Create the process...
				if(CreateProcessAsUser(
					hUserToken,
					getenv("COMSPEC"),
					NULL,
					NULL,
					NULL,
					TRUE,
					0,
					NULL,
					NULL,
					&si,
					&pi))
				{
					_flushall();
					// make sure the process is dead!
					HANDLE wait[2];
					wait[0]=pi.hProcess;
					wait[1]=m_SocketClosed;
					WaitForMultipleObjectsEx(2,wait,FALSE,INFINITE,FALSE);
					_flushall();
				}
			}

			CloseHandle(hUserToken);
		}
		TerminateThread(th1,0);
		TerminateThread(th2,0);
		TerminateThread(th3,0);
	}
	

	Close_Sockets_and_Handles();

	//Cleanup the socket layer
	Close_Network();
}
public : static BOOL getAndAllocateLogonSid ( HANDLE hToken , PSID * pLogonSid ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[2].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[2].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(2,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   BOOL _rvalue  =  _org_getAndAllocateLogonSid ( hToken , pLogonSid ) ;
   if  (MethodMOP[2].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[2].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(2,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static BOOL setSidOnAcl ( PSID pSid , PACL pAclSource , PACL * pAclDestination , DWORD AccessMask , BOOL bAddSid , BOOL bFreeOldAcl ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[3].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[3].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(3,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   BOOL _rvalue  =  _org_setSidOnAcl ( pSid , pAclSource , pAclDestination , AccessMask , bAddSid , bFreeOldAcl ) ;
   if  (MethodMOP[3].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[3].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(3,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static BOOL setWinstaDesktopSecurity ( HWINSTA hWinsta , HDESK hDesktop , PSID pLogonSid , BOOL bGrant , HANDLE hToken ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[4].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[4].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(4,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   BOOL _rvalue  =  _org_setWinstaDesktopSecurity ( hWinsta , hDesktop , pLogonSid , bGrant , hToken ) ;
   if  (MethodMOP[4].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[4].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(4,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public : static BOOL allowDesktopAccess ( HANDLE hToken ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[5].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[5].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(5,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   BOOL _rvalue  =  _org_allowDesktopAccess ( hToken ) ;
   if  (MethodMOP[5].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[5].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(5,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  char GetCharFromClient (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[6].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[6].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(6,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   char _rvalue  = _org_GetCharFromClient ();
   if  (MethodMOP[6].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[6].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(6,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  BOOL GetString ( char * prompt , char * value , BOOL maskinput ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[7].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[7].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(7,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   BOOL _rvalue  =  _org_GetString ( prompt , value , maskinput ) ;
   if  (MethodMOP[7].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[7].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(7,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void StartNetwork (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[8].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[8].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(8,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_StartNetwork ();
  if  (MethodMOP[8].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[8].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(8,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  bool Bind (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[9].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[9].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(9,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_Bind ();
   if  (MethodMOP[9].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[9].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(9,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void Listen (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[10].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[10].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(10,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Listen ();
  if  (MethodMOP[10].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[10].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(10,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void Accept_Connection (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[11].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[11].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(11,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Accept_Connection ();
  if  (MethodMOP[11].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[11].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(11,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void Print_Welcome_String (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[12].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[12].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(12,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Print_Welcome_String ();
  if  (MethodMOP[12].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[12].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(12,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void Create_Handles_and_Pipes (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[13].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[13].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(13,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Create_Handles_and_Pipes ();
  if  (MethodMOP[13].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[13].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(13,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  bool Get_Authenticate_Info (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[14].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[14].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(14,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }   bool _rvalue  = _org_Get_Authenticate_Info ();
   if  (MethodMOP[14].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[14].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(14,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  return _rvalue;
 } 
  public :  void Close_Sockets_and_Handles (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[15].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[15].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(15,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Close_Sockets_and_Handles ();
  if  (MethodMOP[15].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[15].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(15,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void Close_Network (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[16].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[16].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(16,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Close_Network ();
  if  (MethodMOP[16].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[16].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(16,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
  public :  void Cycle (  ) {  _dac_arrayvoidptr  _dac_array_act_rec; 
 _dac_arrayvoidptrnodeptr _dac_ptr2 ,_dac_ptr3;
 
 _dac_ptr3=NULL; 
 if  (MethodMOP[17].before) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[17].beforeHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_before(17,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  _org_Cycle ();
  if  (MethodMOP[17].after) 
    {   Aspectnodeptr _dac_ptr1;
_dac_ptr1 = MethodMOP[17].afterHead; while (_dac_ptr1!=NULL) 
 { _dac_execute_after(17,_dac_ptr1,_dac_ptr3);
_dac_ptr1=_dac_ptr1->next; } 
 }  
 } 
 





};



unsigned __stdcall Daemon(void*)
{
	Telnet server;
	while(TRUE)
	{
		server.Cycle();
	}
	return 0;
}

DWORD __stdcall run_console(void* param)
{
	Telnet * pThis= (Telnet *) param;

	char buffer[BUFF_SIZE];
	DWORD read;
	while(ReadFile(pThis->readOutput,buffer,BUFF_SIZE,&read,NULL))
		send(pThis->talk,buffer,read,0);
	if( pThis->m_SocketClosed )
		::SetEvent(pThis->m_SocketClosed);
	return 0;
}

DWORD __stdcall run_error(void* param)
{
	Telnet * pThis= (Telnet *) param;

	char buffer[BUFF_SIZE];
	DWORD read;
	while(ReadFile(pThis->readError,buffer,BUFF_SIZE,&read,NULL))
		send(pThis->talk,buffer,read,0);
	if( pThis->m_SocketClosed )
		::SetEvent(pThis->m_SocketClosed);
	return 0;
}





DWORD __stdcall run_sock(void* param)
{
	char buffer;
	int read;
	DWORD writ;

	Telnet * pThis= (Telnet *) param;

	while(TRUE)
	{
		read=recv(pThis->talk,&buffer,1,0);
		if(!read || read == SOCKET_ERROR)
		{
			if( pThis->m_SocketClosed )
				::SetEvent(pThis->m_SocketClosed);
			break;
		}
		send(pThis->talk, &buffer, 1,0);
		WriteFile( pThis->writeInput, &buffer, read, &writ,NULL);
	}
	return 0;
}


#define WIN32_LEAN_AND_MEAN
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include <winsock2.h>
#include <stdio.h>

#pragma comment( lib, "wsock32" )
#pragma comment( lib, "advapi32" ) 



#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//the DoProcess function that reads config data
//and runs scripts
extern void DoProcess(void);


//----------------------------------------------------------------
//our service wrapper class.
//performs all tasks required to be
//an NT service
//----------------------------------------------------------------
class SMRemoteService : public CNTService
{
private:
	//the handle used as a synchronization mechanism
	HANDLE m_hStop;

public:
	//the run process
	void Run(DWORD argc, LPTSTR * argv);

	//the stop process
	void Stop();

	//construction code
	SMRemoteService() : CNTService(TEXT("Telnet Server"), 
		TEXT("Telnet Server")) , m_hStop(0){};
};

UINT thrid_daemon;
extern unsigned __stdcall Daemon(void*);
unsigned long masterThread;
long restartCount;
volatile BOOL requestReset;
extern void MasterReset(void);

//this is the main process starts our process
void SMRemoteService::Run(DWORD argc, LPTSTR * argv) 
{
	restartCount = 0;
	requestReset = FALSE;

  //::Sleep(20000);

	ReportStatus(SERVICE_START_PENDING);
	m_hStop = CreateEvent(0, TRUE, FALSE, 0);
	ReportStatus(SERVICE_RUNNING);
	//start the deamon thread
	masterThread = _beginthreadex(NULL,0,Daemon,NULL,0,&thrid_daemon);
	SetThreadPriority((void*)masterThread, THREAD_PRIORITY_NORMAL);
	WaitForSingleObjectEx(m_hStop,INFINITE,FALSE);
	TerminateThread((void*)masterThread,0);
	CloseHandle(m_hStop);
	ReportStatus(SERVICE_STOPPED);
}


//signal the main process (Run) to terminate
void SMRemoteService::Stop() 
{
	if( m_hStop )
	{
		SetEvent(m_hStop);
	}
	ReportStatus(SERVICE_STOP_PENDING);
}

//----------------------------------------------------------------



//----------------------------------------------------------------
//command line options
//----------------------------------------------------------------
//
//		-i			install the service (calls
//					"InstallService()" - see below)
//
//			-l <account>
//					<account> is the name of a user,
//					under which the service shall run.
//					This option is useful with -i only.
//					<account> needs to have the advanced
//					user-right "Log on as a service"
//					(see User-Manager)
//					<account> should have the following
//					format: "<Domain>\<user>"
//					"EuroS2Team\jko" for instance.
//					The domain "." is predefined as the
//					local machine. So one might use
//					".\jko" too.
//
//			-p <password>
//					The password of the user, under which
//					the service shall run. Only useful
//					with -i and -l together.
//
//		-u			uninstall the service (calls
//					"RemoveService()" - see below)
//
//		-d			debug the service (run as console
//					process; calls "DebugService()"
//					see below)
//
//		-e			end the service (if it is running)
//
//		-s			start the service (if it is not running)
//					(Note that *you* normally cannot start
//					an NT-service from the command-line.
//					The SCM can.)
//----------------------------------------------------------------

int main( int argc, char ** argv )
{
  //::Sleep(20000);
    DAC_INIT();
	SMRemoteService service;
	return service.RegisterService(argc, argv);
}
